import math
import numpy as np


# get csi scale
def GetScaleCsi(csiSt):
    # csiSt: call bfee ,get bfee.dicts
    # Pull out csi
    csi = csiSt['csi']

    # Calculate the scale factor between normalized CSI and RSSI (mW)
    csiSq = np.multiply(csi, np.conj(csi)).real
    csiPwr = np.sum(csiSq, axis=0)
    csiPwr = csiPwr.reshape(1, csiPwr.shape[0], -1)
    csiTemp = GetTotalRss(csiSt)
    rssiPwr = Dbinv(csiTemp)
    csiTemp = csiPwr/30
    scale = rssiPwr / csiTemp

    if csiSt['noise'] == -127:
        noiseDb = -92
    else:
        noiseDb = csiSt['noise']

    thermalNoisePwr = Dbinv(noiseDb)
    csiTemp = csiSt['Nrx']*csiSt['Ntx']
    quantErrorPwr = scale * csiTemp
    totalNoisePwr = thermalNoisePwr + quantErrorPwr
    csiTemp = scale / totalNoisePwr
    valueTemp = np.sqrt(csiTemp)
    returnValue = csi * valueTemp

    if csiSt['Ntx'] == 2:
        csiTemp = math.sqrt(2)
        returnValue = returnValue * csiTemp
    elif csiSt['Ntx'] == 3:
        csiTemp = Dbinv(4.5)
        valueTemp = math.sqrt(csiTemp)
        returnValue = returnValue * valueTemp
    return returnValue


# get rss
def GetTotalRss(csiSt):
    # Careful here: rss could be zero
    rssiMag = 0
    tempValueA=Dbinv(csiSt['rssi_a'])
    tempValueB = Dbinv(csiSt['rssi_b'])
    tempValueC = Dbinv(csiSt['rssi_c'])
    if csiSt['rssi_a'] != 0:
        rssiMag = rssiMag + tempValueA
    if csiSt['rssi_b'] != 0:
        rssiMag = rssiMag + tempValueB
    if csiSt['rssi_c'] != 0:
        rssiMag = rssiMag + tempValueC
    csiTemp = Db(rssiMag,'Power')
    valueTemp = csiTemp - 44 - csiSt['agc']
    return valueTemp


# calculate pow(10,x/10)
def Dbinv(paramrterX):
    csiTemp = paramrterX / 10
    valueTemp = math.pow(10,csiTemp)
    return valueTemp


# calculate return value of total rss
def Db(parameterX, parameterU):
    DENOMINATOR = 1
    if 'power'.startswith(parameterU):
        assert parameterX >= 0
    else:
        csiTemp = abs(parameterX)
        valueTemp = math.pow(csiTemp, 2)
        parameterX = valueTemp / DENOMINATOR
        csiTemp = math.log10(parameterX)
        valueTemp = 10 * csiTemp
    return valueTemp
